﻿using System.Diagnostics;

namespace STranslate.Util.Proxy;

internal static class SimpleRegex
{
    // Based on wildcmp written by Jack Handy - <A href="mailto:jakkhandy@hotmail.com">jakkhandy@hotmail.com</A>
    // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing

    /// <summary>
    ///     Perform a match between an input string and a pattern in which the only special character
    ///     is an asterisk, which can map to zero or more of any character in the input.
    /// </summary>
    /// <param name="input">The input to match.</param>
    /// <param name="pattern">The pattern to match against.</param>
    /// <returns>true if the input matches the pattern; otherwise, false.</returns>
    public static bool IsMatchWithStarWildcard(ReadOnlySpan<char> input, ReadOnlySpan<char> pattern)
    {
        int inputPos = 0,
            inputPosSaved = -1;
        int patternPos = 0,
            patternPosSaved = -1;

        // Loop through each character in the input.
        while (inputPos < input.Length)
            if (patternPos < pattern.Length && pattern[patternPos] == '*')
            {
                // If we're currently positioned on a wildcard in the pattern,
                // move past it and remember where we are to backtrack to.
                inputPosSaved = inputPos;
                patternPosSaved = ++patternPos;
            }
            else if (
                patternPos < pattern.Length
                && (
                    pattern[patternPos] == input[inputPos]
                    || char.ToUpperInvariant(pattern[patternPos]) == char.ToUpperInvariant(input[inputPos])
                )
            )
            {
                // If the characters in the pattern and the input match, advance both.
                inputPos++;
                patternPos++;
            }
            else if (patternPosSaved == -1)
            {
                // If we're not on a wildcard and the current characters don't match and we don't have
                // any wildcard to backtrack to, this is not a match.
                return false;
            }
            else
            {
                // Otherwise, this is not a wildcard, the characters don't match, but we do have a
                // wildcard saved, so backtrack to it and use it to consume the next input character.
                inputPos = ++inputPosSaved;
                patternPos = patternPosSaved;
            }

        // We've reached the end of the input.  Eat all wildcards immediately after where we are
        // in the pattern, as if they're at the end, they'll all just map to nothing (and if it
        // turns out there's something after them, eating them won't matter).
        while (patternPos < pattern.Length && pattern[patternPos] == '*') patternPos++;

        // If we are in fact at the end of the pattern, then we successfully matched.
        // If there's anything left, it's not a wildcard, so it doesn't match.
        Debug.Assert(patternPos <= pattern.Length);
        return patternPos == pattern.Length;
    }
}